﻿/*
 * zlog.cxx
 *
 *  Created on: 2014年9月30日
 *      Author: Fifi Lyu
 */

#include "zpsoe/zlog.h"
#include "zpsoe/common.h"
#include "zpsoe/config_platform.h"
#include "zpsoe/zerrno.h"

#ifdef PLATFORM_WIN32
    #include <process.h>

    #ifndef INCLUDE_WINDOWS_H_FILE
        #define INCLUDE_WINDOWS_H_FILE
        #include <Windows.h>
    #endif
#else
    #include <unistd.h>
#endif

#include <sys/stat.h>
#include <cstdio>
#include <cstdlib>
#include <cstdarg>
#include <cstring>
#include <sstream>
#include <ctime>
#include <iostream>

using std::cerr;
using std::endl;
using zpsoe::zerrno::error_to_str;

namespace zpsoe {

namespace zlog {

#ifdef PLATFORM_WIN32
// 104857600 byte == 100 MiB
log_config_t G_LOG_CONFIG = {LOG_INFO, LOS_FILE, 104857600, "C:\\Windows\\temp\\tmp.log"};
#else
// 104857600 byte == 100 MiB
log_config_t G_LOG_CONFIG = {LOG_INFO, LOS_FILE, 104857600, "/tmp/tmp.log" };
#endif

size_t get_size_in_byte(const string &file_name) {
    struct stat buf_;

    if (stat(file_name.c_str(), &buf_) == 0)
        return buf_.st_size;

    return 0;
}

void open_log_file(FILE **file) {
    const size_t old_log_size_ = get_size_in_byte(G_LOG_CONFIG.path);

    if (old_log_size_ >= G_LOG_CONFIG.max_byte)
        // 覆盖
        *file = fopen(G_LOG_CONFIG.path.c_str(), "wb");
    else
        // 追加
        *file = fopen(G_LOG_CONFIG.path.c_str(), "ab+");

    if (*file == NULL) {
        const string err_("cannot open \"" + G_LOG_CONFIG.path + "\": " + error_to_str());
        cerr << err_ << endl;
        exit(EXIT_FAILURE);
    }
}

ZPSOE_SHARED_LIB_API string get_current_date() {
    char buf[80];
    time_t t = time(NULL);
    strftime(buf, 80, "%Y-%m-%d %H:%M:%S", localtime(&t));
    return string(buf);
}

ZPSOE_SHARED_LIB_API void _print_log(
        log_level_t level, const char *file,
        int line, const char *fmt, ...) {
    // 关闭日志
    if (level == LOG_OFF)
        return;

    // 关闭比用户设置更加详细的日志
    if (level < G_LOG_CONFIG.level)
        return;

    FILE *log_file_ = NULL;

    switch (G_LOG_CONFIG.output_to) {
        case LOS_STDOUT:
            log_file_ = stdout;
            break;
        case LOS_STDERR:
            log_file_ = stderr;
            break;
        case LOS_FILE:
            open_log_file(&log_file_);
            break;
        default:
            log_file_ = stdout;
            break;
    }

#ifdef PLATFORM_WIN32
    static int pid_ = _getpid();
#else
    static int pid_ = getpid();
#endif

    fprintf(log_file_, "[%s] [%d] ", get_current_date().c_str(), pid_);

    if (level <= LOG_TRACE)
        fprintf(log_file_, "%s:%d ", file, line);

    va_list ap_;
    va_start(ap_, fmt);
    vfprintf(log_file_, fmt, ap_);
    va_end(ap_);

    fprintf(log_file_, OS_LINE_FEED.c_str());
    fflush(log_file_);

    if (G_LOG_CONFIG.output_to == LOS_FILE)
        fclose(log_file_);
}

} /* namespace zlog */

} /* namespace zpsoe */
